﻿using MongoDB.Driver;
using Sustainalytics.Synchronization.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sustainalytics.ClientDW.Synchronization.SyncRiskRatingsData.Helpers
{
    public class SyncCommand
    {
        private readonly CollectionFactory _collectionFactory;
        private readonly ILogger _logger;
        private readonly int _insertManyBatchSize;

        public SyncCommand(CollectionFactory collectionFactory, ILogger logger, int insertManyBatchSize)
        {
            _collectionFactory = collectionFactory;
            _logger = logger;
            _insertManyBatchSize = insertManyBatchSize;
        }

        public async Task ExecuteAsync<T>(IEnumerable<T> entities, Func<IMongoCollection<T>, Task> recreateIndexes = null, bool dropCollection = true)
        {
            var mongoCollection = _collectionFactory.Get<T>();

            if (dropCollection)
            {
                await mongoCollection.Database.DropCollectionAsync(typeof(T).Name);
                _logger.Log($"collection {typeof(T).Name} droped.");
            }

            if (entities != null && entities.Any(x => !Equals(x, default(T))))
            {
                //Remove null entities
                entities = entities.Where(x => !Equals(x, default(T))).ToList();

                var skip = 0;
                while (entities.Count() > skip)
                {
                    var entitiesToInsert = entities.Skip(skip).Take(_insertManyBatchSize);
                    await mongoCollection.InsertManyAsync(entitiesToInsert);
                    skip += _insertManyBatchSize;
                }

                _logger.Log($"inserted a total of {entities.Count()} in collection {typeof(T).Name}.");
            }

            if (recreateIndexes != null)
            {
                await recreateIndexes(mongoCollection);
                _logger.Log($" collection {typeof(T).Name} index recreated.");
            }
        }
    }
}
